package com.reactim.message.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 连接数据加密组件
 * 提供敏感连接信息的加密和解密功能
 */
@Component
@Slf4j
public class ConnectionEncryption {
    
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/GCM/NoPadding";
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;
    
    private final SecretKey secretKey;
    private final SecureRandom secureRandom;
    
    public ConnectionEncryption(@Value("${connection.security.encryption.key:}") String encryptionKey) {
        this.secureRandom = new SecureRandom();
        
        if (encryptionKey != null && !encryptionKey.trim().isEmpty()) {
            // 使用配置的密钥
            byte[] keyBytes = Base64.getDecoder().decode(encryptionKey);
            this.secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            log.info("使用配置的加密密钥初始化连接加密组件");
        } else {
            // 生成新的密钥
            this.secretKey = generateSecretKey();
            log.warn("未配置加密密钥，使用随机生成的密钥。生产环境请配置固定密钥: {}", 
                    Base64.getEncoder().encodeToString(secretKey.getEncoded()));
        }
    }
    
    /**
     * 生成AES密钥
     */
    private SecretKey generateSecretKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            keyGenerator.init(256);
            return keyGenerator.generateKey();
        } catch (Exception e) {
            throw new RuntimeException("生成加密密钥失败", e);
        }
    }
    
    /**
     * 加密敏感数据
     * 
     * @param plainText 明文数据
     * @return 加密后的Base64编码字符串
     */
    public String encrypt(String plainText) {
        if (plainText == null || plainText.isEmpty()) {
            return plainText;
        }
        
        try {
            // 生成随机IV
            byte[] iv = new byte[GCM_IV_LENGTH];
            secureRandom.nextBytes(iv);
            
            // 初始化加密器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            GCMParameterSpec parameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
            
            // 加密数据
            byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            
            // 将IV和加密数据合并
            byte[] encryptedWithIv = new byte[GCM_IV_LENGTH + encryptedData.length];
            System.arraycopy(iv, 0, encryptedWithIv, 0, GCM_IV_LENGTH);
            System.arraycopy(encryptedData, 0, encryptedWithIv, GCM_IV_LENGTH, encryptedData.length);
            
            // 返回Base64编码的结果
            return Base64.getEncoder().encodeToString(encryptedWithIv);
            
        } catch (Exception e) {
            log.error("数据加密失败: {}", e.getMessage());
            throw new RuntimeException("数据加密失败", e);
        }
    }
    
    /**
     * 解密敏感数据
     * 
     * @param encryptedText 加密的Base64编码字符串
     * @return 解密后的明文数据
     */
    public String decrypt(String encryptedText) {
        if (encryptedText == null || encryptedText.isEmpty()) {
            return encryptedText;
        }
        
        try {
            // Base64解码
            byte[] encryptedWithIv = Base64.getDecoder().decode(encryptedText);
            
            // 提取IV
            byte[] iv = new byte[GCM_IV_LENGTH];
            System.arraycopy(encryptedWithIv, 0, iv, 0, GCM_IV_LENGTH);
            
            // 提取加密数据
            byte[] encryptedData = new byte[encryptedWithIv.length - GCM_IV_LENGTH];
            System.arraycopy(encryptedWithIv, GCM_IV_LENGTH, encryptedData, 0, encryptedData.length);
            
            // 初始化解密器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            GCMParameterSpec parameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
            
            // 解密数据
            byte[] decryptedData = cipher.doFinal(encryptedData);
            
            return new String(decryptedData, StandardCharsets.UTF_8);
            
        } catch (Exception e) {
            log.error("数据解密失败: {}", e.getMessage());
            throw new RuntimeException("数据解密失败", e);
        }
    }
    
    /**
     * 检查是否已加密
     * 
     * @param data 数据
     * @return 是否为加密数据
     */
    public boolean isEncrypted(String data) {
        if (data == null || data.isEmpty()) {
            return false;
        }
        
        try {
            // 尝试Base64解码
            byte[] decoded = Base64.getDecoder().decode(data);
            // 检查长度是否合理（至少包含IV + 最小加密数据）
            return decoded.length > GCM_IV_LENGTH + GCM_TAG_LENGTH;
        } catch (Exception e) {
            return false;
        }
    }
}